<script>
  import { createEventDispatcher } from "svelte";

  const dispatch = createEventDispatcher();

  export let selectedValues = []; // 现在存储的是节点ID数组
  export let disabled = false;
  export let placeholder = "请选择部门";
  export let treeData = []; // 改为外部属性，默认空数组
  export let idKey = "id"; // 自定义ID字段名
  export let nameKey = "name"; // 自定义名称字段名
  export let childrenKey = "children"; // 自定义子节点字段名
  export let maxVisibleTags = 0; // 最多显示的标签数量，0表示不限制

  let showDropdown = false;
  let expandedNodes = new Set(); // 默认不展开，根据数据动态设置
  let visibleNodes = [];
  let displayTags = [];

  // 缓存优化
  let nodeCache = new Map();
  let pathCache = new Map();
  let childrenCache = new Map();
  let parentCache = new Map();
  let lastSelectedValues = [];
  let lastExpandedNodes = new Set();
  let lastTreeData = [];

  // 防抖函数
  function debounce(func, wait) {
    let timeout;
    return function executedFunction(...args) {
      const later = () => {
        clearTimeout(timeout);
        func(...args);
      };
      clearTimeout(timeout);
      timeout = setTimeout(later, wait);
    };
  }

  // 清除缓存
  function clearCaches() {
    nodeCache.clear();
    pathCache.clear();
    childrenCache.clear();
    parentCache.clear();
  }

  // 获取节点ID
  function getNodeId(node) {
    return node[idKey];
  }

  // 获取节点名称
  function getNodeName(node) {
    return node[nameKey];
  }

  // 获取子节点
  function getNodeChildren(node) {
    return node[childrenKey] || [];
  }

  // 缓存节点查找
  function findNodeById(nodeId, tree = treeData) {
    if (nodeCache.has(nodeId)) {
      return nodeCache.get(nodeId);
    }

    function search(nodes) {
      for (let node of nodes) {
        if (getNodeId(node) === nodeId) {
          nodeCache.set(nodeId, node);
          return node;
        }
        const children = getNodeChildren(node);
        if (children && children.length > 0) {
          const found = search(children);
          if (found) return found;
        }
      }
      return null;
    }

    const result = search(tree);
    if (result) nodeCache.set(nodeId, result);
    return result;
  }

  // 缓存路径计算
  function getNodePath(nodeId, tree = treeData, path = []) {
    if (pathCache.has(nodeId)) {
      return pathCache.get(nodeId);
    }

    function search(nodes, currentPath) {
      for (let node of nodes) {
        const nodeName = getNodeName(node);
        const newPath = [...currentPath, nodeName];

        if (getNodeId(node) === nodeId) {
          const result = newPath.join("/");
          pathCache.set(nodeId, result);
          return result;
        }

        const children = getNodeChildren(node);
        if (children && children.length > 0) {
          const result = search(children, newPath);
          if (result) {
            return result;
          }
        }
      }
      return null;
    }

    const result = search(tree, path);
    if (result) {
      pathCache.set(nodeId, result);
    }
    return result;
  }

  // 缓存子节点ID
  function getAllChildIds(node) {
    const nodeId = getNodeId(node);
    if (childrenCache.has(nodeId)) {
      return childrenCache.get(nodeId);
    }

    let ids = [];
    const children = getNodeChildren(node);
    if (children && children.length > 0) {
      for (let child of children) {
        ids.push(getNodeId(child));
        ids = [...ids, ...getAllChildIds(child)];
      }
    }

    childrenCache.set(nodeId, ids);
    return ids;
  }

  // 缓存父节点ID
  function getAllParentIds(nodeId, tree = treeData, parents = []) {
    if (parentCache.has(nodeId)) {
      return parentCache.get(nodeId);
    }

    function search(nodes, currentParents) {
      for (let node of nodes) {
        const newParents = [...currentParents, getNodeId(node)];
        if (getNodeId(node) === nodeId) {
          parentCache.set(nodeId, currentParents);
          return currentParents;
        }
        const children = getNodeChildren(node);
        if (children && children.length > 0) {
          const result = search(children, newParents);
          if (result) return result;
        }
      }
      return null;
    }

    return search(tree, parents);
  }

  // 切换节点展开状态
  function toggleExpand(nodeId) {
    if (expandedNodes.has(nodeId)) {
      expandedNodes.delete(nodeId);
    } else {
      expandedNodes.add(nodeId);
    }
    expandedNodes = expandedNodes;

    // 展开后需要强制重新计算可见节点的选择状态
    setTimeout(() => {
      visibleNodes = renderTreeNodes(treeData);
    }, 10);
  }
 

  // 切换选择状态函数
  function toggleSelection(nodeId, event) {
    if (event) {
      event.stopPropagation();
    }

    const currentState = getNodeSelectionState(nodeId);
    const node = findNodeById(nodeId);
    if (!node) return;

    // 获取直系父节点
    const parentIds = getAllParentIds(nodeId);
    const directParentId = parentIds && parentIds.length > 0 ? parentIds[parentIds.length - 1] : null;
    const isDirectlySelected = selectedValues.includes(nodeId);
    const isParentSelected = directParentId && selectedValues.includes(directParentId);

    if (currentState === "full") {
      if (isDirectlySelected) {
        // 节点直接被选中 -> 取消选择它和它的子节点
        const childIds = getAllChildIds(node);
        const idsToRemove = [nodeId, ...childIds];
        selectedValues = selectedValues.filter(id => !idsToRemove.includes(id));
      } else if (isParentSelected) {
        // 节点因父节点选中而显示选中 -> 保留它的兄弟节点选中状态
        
        // 1. 先从选中列表中移除父节点
        selectedValues = selectedValues.filter(id => id !== directParentId);
        
        // 2. 找到所有兄弟节点（除了当前节点外的所有子节点）
        const parentNode = findNodeById(directParentId);
        if (parentNode) {
          const siblings = getNodeChildren(parentNode);
          const siblingIds = siblings
            .map(sibling => getNodeId(sibling))
            .filter(id => id !== nodeId);
          
          // 3. 将所有兄弟节点及其后代添加到选中列表
          for (const siblingId of siblingIds) {
            const siblingNode = findNodeById(siblingId);
            if (siblingNode) {
              const siblingDescendants = getAllChildIds(siblingNode);
              selectedValues = [...selectedValues, siblingId, ...siblingDescendants];
            }
          }
        }
      }
    } else {
      // 未选择或半选状态 -> 全选：添加节点本身和所有子孙节点
      const childIds = getAllChildIds(node);
      const idsToAdd = [nodeId, ...childIds];
      selectedValues = [...new Set([...selectedValues, ...idsToAdd])];
    }

    // 更新祖先节点状态
    updateAncestorStates(nodeId);

    // 防抖派发事件
    debouncedDispatch();
  }

  // 新增：获取有效显示ID的函数
  function getDisplayIds(ids) {
    const displayIds = [];
    
    for (let id of ids) {
      // 检查是否有被选中的父节点包含此节点
      const hasSelectedParent = ids.some(parentId => {
        if (parentId === id) return false;
        const parentNode = findNodeById(parentId);
        if (!parentNode) return false;
        return getAllChildIds(parentNode).includes(id);
      });
      
      // 只添加没有被选中父节点的节点
      if (!hasSelectedParent) {
        displayIds.push(id);
      }
    }
    
    return displayIds;
  }

  // 防抖派发change事件
  const debouncedDispatch = debounce(() => {
    const displayIds = getDisplayIds(selectedValues);
    dispatch("change", { selectedValues, displayIds });
  }, 50);

  // 渲染树节点 
  function renderTreeNodes(nodes, level = 0) {
    let result = [];

    for (let node of nodes) {
      const nodeId = getNodeId(node);
      const nodeName = getNodeName(node);
      const children = getNodeChildren(node);
      const hasChildren = children && children.length > 0;
      const isExpanded = expandedNodes.has(nodeId);

      // 每次渲染都重新计算选择状态，不使用缓存
      const selectionState = getNodeSelectionState(nodeId);

      result.push({
        id: nodeId,
        name: nodeName,
        level,
        hasChildren,
        isExpanded,
        selectionState: selectionState, // 确保使用最新的选择状态
        path: getNodePath(nodeId),
      });

      if (hasChildren && isExpanded) {
        result = [...result, ...renderTreeNodes(children, level + 1)];
      }
    }

    return result;
  }

  // 优化的显示标签计算
  function getDisplayTags() {
    const displayIds = getDisplayIds(selectedValues);

    const allTags = displayIds
      .map((id) => {
        const path = getNodePath(id);
        return {
          id,
          path: path || `节点_${id}`, // 如果路径为null，使用备用显示
        };
      })
      .filter((tag) => tag.path);

    // 如果设置了标签数量限制且超出限制，则分割显示
    if (maxVisibleTags > 0 && allTags.length > maxVisibleTags) {
      return {
        visibleTags: allTags.slice(0, maxVisibleTags),
        hiddenCount: allTags.length - maxVisibleTags,
        allTags: allTags,
      };
    }

    return {
      visibleTags: allTags,
      hiddenCount: 0,
      allTags: allTags,
    };
  }

 
  // 初始化默认展开节点
  function initDefaultExpanded() {
    if (treeData.length > 0) {
      const firstNode = treeData[0];
      const firstNodeId = getNodeId(firstNode);
      expandedNodes.add(firstNodeId);

      const children = getNodeChildren(firstNode);
      if (children && children.length > 0) {
        const firstChildId = getNodeId(children[0]);
        expandedNodes.add(firstChildId);
      }
      expandedNodes = expandedNodes;
    }
  }

  // 点击外部关闭下拉
  function handleClickOutside(event) {
    if (!event.target.closest(".tree-select-container")) {
      showDropdown = false;
    }
  }

  // 检查节点选择状态（全选、半选、未选） 
  function getNodeSelectionState(nodeId) {
     
    const node = findNodeById(nodeId);
    if (!node) return "none";

    // 首先检查上层节点是否已选中
    const parentIds = getAllParentIds(nodeId);
    if (parentIds && parentIds.length > 0) {
      // 检查是否有任何父节点被选中
      const hasSelectedParent = parentIds.some((parentId) =>
        selectedValues.includes(parentId)
      );
      if (hasSelectedParent) {
        return "full"; // 如果父节点被选中，子节点显示为全选状态
      }
    }

    const isDirectlySelected = selectedValues.includes(nodeId);
    const children = getNodeChildren(node);

    // 如果没有子节点，直接返回选择状态
    if (!children || children.length === 0) {
      return isDirectlySelected ? "full" : "none";
    }

    // 如果父节点直接被选中，返回full
    if (isDirectlySelected) {
      return "full";
    }

    // 检查所有子孙节点的选择状态
    const allChildIds = getAllChildIds(node);
    const selectedChildren = allChildIds.filter((id) =>
      selectedValues.includes(id)
    );

    if (selectedChildren.length === 0) {
      return "none";
    } else if (selectedChildren.length === allChildIds.length) {
      return "full";
    } else {
      return "partial";
    }
  }

  // 移除选中项
  function removeSelected(nodeId) {
    const node = findNodeById(nodeId);
    if (!node) return;

    const childIds = getAllChildIds(node);
    const idsToRemove = [nodeId, ...childIds];

    // 移除节点和所有子节点
    selectedValues = selectedValues.filter((id) => !idsToRemove.includes(id));

    // 更新所有祖先节点状态
    updateAncestorStates(nodeId);
    
    const displayIds = getDisplayIds(selectedValues);
    dispatch("change", { selectedValues, displayIds });
  }

  // 统一的祖先节点状态更新方法
  function updateAncestorStates(nodeId) {
    const parentIds = getAllParentIds(nodeId);
    if (!parentIds || parentIds.length === 0) return;
    
    // 从最深层的父节点开始向上更新
    for (let i = parentIds.length - 1; i >= 0; i--) {
      const ancestorId = parentIds[i];
      const ancestorNode = findNodeById(ancestorId);
      if (!ancestorNode) continue;
      
      const children = getNodeChildren(ancestorNode);
      if (!children || children.length === 0) continue;
      
      const directChildIds = children.map(child => getNodeId(child));
      
      // 检查所有子节点的状态
      const allChildrenSelected = directChildIds.every(childId => {
        const childNode = findNodeById(childId);
        if (!childNode) return false;
        
        // 如果子节点本身被选中，返回true
        if (selectedValues.includes(childId)) return true;
        
        // 如果子节点有后代，检查是否所有后代都被选中
        const allDescendantIds = getAllChildIds(childNode);
        if (allDescendantIds.length === 0) return false;
        
        return allDescendantIds.every(id => selectedValues.includes(id));
      });
      
      if (allChildrenSelected && directChildIds.length > 0) {
        // 所有子节点都被选中，选中父节点并移除所有子节点
        if (!selectedValues.includes(ancestorId)) {
          selectedValues = [...selectedValues, ancestorId];
        }
        
        // 收集所有子孙节点ID
        const allDescendantIds = [];
        for (const childId of directChildIds) {
          const childNode = findNodeById(childId);
          if (childNode) {
            allDescendantIds.push(childId, ...getAllChildIds(childNode));
          }
        }
        
        // 从选中列表中移除所有子孙节点
        selectedValues = selectedValues.filter(id => !allDescendantIds.includes(id));
      } else {
        // 不是所有子节点都被选中，确保父节点未被选中
        selectedValues = selectedValues.filter(id => id !== ancestorId);
      }
    }
  }

  // 简化响应式更新，确保每次都重新计算
  $: {
    if (treeData !== lastTreeData) {
      clearCaches();
      if (treeData.length > 0 && expandedNodes.size === 0) {
        initDefaultExpanded();
      }
      lastTreeData = treeData;
    }
  }

  // 监听selectedValues变化并打印
  $: {
    console.log("selectedValues changed:", selectedValues);
    // node
    console.log("visibleNodes changed:", visibleNodes);
  }

  $: {
    selectedValues;
    displayTags = getDisplayTags();
  }

  $: {
    // 当选择状态、展开状态或数据变化时，重新渲染
    selectedValues;
    expandedNodes;
    treeData;
    visibleNodes = renderTreeNodes(treeData);
  }

  // 单独监听展开状态变化
  $: {
    expandedNodes;
    // 展开状态变化时，延迟重新计算可见节点
    if (expandedNodes.size > 0) {
      setTimeout(() => {
        visibleNodes = [...renderTreeNodes(treeData)];
      }, 0);
    }
  }
</script>

<svelte:window on:click={handleClickOutside} />

<div class="tree-select-container">
  <!-- 下拉触发器 -->
  <div
    class="select-trigger"
    class:disabled
    on:click={() => !disabled && (showDropdown = !showDropdown)}
  >
    <div class="trigger-content">
      <!-- 已选择的标签 -->
      {#if displayTags.visibleTags.length > 0}
        <div class="selected-tags">
          <!-- 显示的标签 -->
          {#each displayTags.visibleTags as { id, path }}
            <span class="tag">
              <span class="tag-text" title={path}>{path}</span>
              {#if !disabled}
                <button
                  class="tag-remove"
                  on:click={(e) => {
                    e.stopPropagation();
                    removeSelected(id);
                  }}
                >
                  ×
                </button>
              {/if}
            </span>
          {/each}

          <!-- 隐藏标签数量提示 -->
          {#if displayTags.hiddenCount > 0}
            <span
              class="tag tag-more"
              title="还有 {displayTags.hiddenCount} 个选项\n{displayTags.allTags
                .slice(maxVisibleTags)
                .map((t) => t.path)
                .join('\n')}"
            >
              <span class="tag-text">+{displayTags.hiddenCount}</span>
              {#if !disabled}
                <button
                  class="tag-remove"
                  on:click={(e) => {
                    e.stopPropagation();
                    // 删除所有隐藏的标签
                    const hiddenIds = displayTags.allTags
                      .slice(maxVisibleTags)
                      .map((t) => t.id);
                    hiddenIds.forEach((id) => removeSelected(id));
                  }}
                >
                  ×
                </button>
              {/if}
            </span>
          {/if}
        </div>
      {:else}
        <span class="placeholder-text">{placeholder}</span>
      {/if}
    </div>

    <svg
      class="arrow-icon"
      class:rotated={showDropdown}
      width="16"
      height="16"
      viewBox="0 0 16 16"
      fill="none"
    >
      <path
        d="M8.00042 8.78028L11.3003 5.48047L12.2431 6.42328L8.00042 10.6659L3.75781 6.42328L4.70062 5.48047L8.00042 8.78028Z"
        fill="#474747"
      />
    </svg>
  </div>

  <!-- 下拉面板 -->
  {#if showDropdown && !disabled}
    <div class="dropdown-panel">
      <!-- 已选择项预览（当有隐藏标签时显示） -->
      {#if displayTags.hiddenCount > 0}
        <div class="selected-preview">
          <div class="preview-header">
            <span class="preview-title"
              >已选择 {displayTags.allTags.length} 项</span
            >
            <button
              class="clear-all-btn"
              on:click={(e) => {
                e.stopPropagation();
                selectedValues = [];
                dispatch("change", { selectedValues });
              }}
            >
              清空全部
            </button>
          </div>
          <div class="preview-tags">
            {#each displayTags.allTags as { id, path }}
              <span class="preview-tag">
                <span class="preview-tag-text" title={path}>{path}</span>
                <button
                  class="preview-tag-remove"
                  on:click={(e) => {
                    e.stopPropagation();
                    removeSelected(id);
                  }}
                >
                  ×
                </button>
              </span>
            {/each}
          </div>
        </div>
      {/if}

      <!-- 树形结构区域 -->
      <div class="tree-area">
        {#each visibleNodes as node (node.id)}
          <div class="tree-node" style="padding-left: {node.level * 24 + 12}px">
            <!-- 展开/折叠按钮 -->
            {#if node.hasChildren}
              <button
                class="expand-btn"
                on:click={(e) => {
                  e.stopPropagation();
                  toggleExpand(node.id);
                }}
              >
                <svg
                  class="expand-icon"
                  class:expanded={node.isExpanded}
                  viewBox="0 0 24 24"
                >
                  <path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" />
                </svg>
              </button>
            {:else}
              <div class="expand-spacer"></div>
            {/if}

            <!-- 复选框和标签 -->
            <div
              class="node-label"
              on:click={(e) => toggleSelection(node.id, e)}
            >
              <span
                class="checkbox-custom"
                class:checked={node.selectionState === "full"}
                class:indeterminate={node.selectionState === "partial"}
              ></span>
              <span class="node-text">{node.name}</span>
            </div>
          </div>
        {/each}
      </div>
    </div>
  {/if}
</div>

<style>
  .tree-select-container {
    position: relative;
    width: 100%;
  }

  .select-trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px;
    border: 1px solid #d0d7de;
    border-radius: 6px;
    background: white;
    cursor: pointer;
    font-size: 14px;
    min-height: 32px;
    transition: border-color 0.2s;
    gap: 8px;
  }

  .select-trigger:hover:not(.disabled) {
    border-color: #0969da;
  }

  .select-trigger.disabled {
    background: #f6f8fa;
    cursor: not-allowed;
    color: #656d76;
  }

  .trigger-content {
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
    min-height: 20px;
  }

  .selected-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    align-items: center;
    max-height: 100px;
    overflow: auto;
  }

  .tag {
    display: inline-flex;
    align-items: center;
    background: rgba(0, 0, 0, 0.07);

    border-radius: 4px;
    padding: 5px 6px;
    font-size: 12px;
    color: #262626;
  }

  .tag-text {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .tag-remove {
    background: none;
    border: none;
    color: #999;
    cursor: pointer;
    margin-left: 4px;
    font-size: 15px;
    line-height: 1;
    padding: 0;
  }

  .tag-remove:hover {
    color: #da3633;
  }

  .placeholder-text {
    color: #656d76;
  }

  .arrow-icon {
    width: 16px;
    height: 16px;
    color: #656d76;
    transition: transform 0.2s;
    fill: currentColor;
    flex-shrink: 0;
  }

  .arrow-icon.rotated {
    transform: rotate(180deg);
  }

  .dropdown-panel {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: white;
    border: 1px solid #d0d7de;
    border-radius: 6px;
    box-shadow: 0 8px 24px rgba(140, 149, 159, 0.2);
    z-index: 1000;
    margin-top: 4px;
    overflow: hidden;
  }

  .tree-area {
    max-height: 250px;
    overflow-y: auto;
    padding: 8px 0;
  }

  .tree-node {
    display: flex;
    align-items: center;
    min-height: 32px;
    padding: 2px 0;
  }

  .expand-btn {
    background: none;
    border: none;
    cursor: pointer;
    padding: 4px;
    color: #656d76;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: 4px;
  }

  .expand-btn:hover {
    background: #f3f4f6;
    border-radius: 3px;
  }

  .expand-spacer {
    width: 24px;
    margin-right: 4px;
  }

  .expand-icon {
    width: 16px;
    height: 16px;
    fill: currentColor;
    transition: transform 0.2s;
  }

  .expand-icon.expanded {
    transform: rotate(90deg);
  }

  .node-label {
    display: flex;
    align-items: center;
    cursor: pointer;
    flex: 1;
    padding: 4px 8px;
    margin: 0;
    border-radius: 3px;
  }

  .node-label:hover {
    background: #f6f8fa;
  }

  .checkbox-custom {
    width: 16px;
    height: 16px;
    border: 1px solid #d0d7de;
    border-radius: 3px;
    background: white;
    position: relative;
    margin-right: 8px;
    transition: all 0.2s;
    cursor: pointer;
  }

  .checkbox-custom::after {
    content: "";
    position: absolute;
    left: 4px;
    top: 1px;
    width: 5px;
    height: 9px;
    border: solid transparent;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
    opacity: 0;
    transition: opacity 0.2s;
  }

  .checkbox-custom.checked {
    background: #0969da;
    border-color: #0969da;
  }

  .checkbox-custom.checked::after {
    border-color: white;
    opacity: 1;
  }

  .checkbox-custom.indeterminate {
    background: #0969da;
    border-color: #0969da;
  }

  .checkbox-custom.indeterminate::after {
    content: "";
    position: absolute;
    left: 3px;
    top: 7px;
    width: 8px;
    height: 2px;
    background: white;
    border: none;
    transform: none;
    opacity: 1;
  }

  .node-text {
    font-size: 14px;
    color: #24292f;
    user-select: none;
  }

  .tag-more {
    background: #e6f3ff;
    border-color: #91caff;
    color: #0969da;
    font-weight: 500;
  }

  .selected-preview {
    background: #f8f9fa;
    border-bottom: 1px solid #d0d7de;
    padding: 8px 12px;
    max-height: 120px;
    overflow-y: auto;
  }

  .preview-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
  }

  .preview-title {
    font-size: 12px;
    color: #656d76;
    font-weight: 500;
  }

  .clear-all-btn {
    background: none;
    border: none;
    color: #da3633;
    cursor: pointer;
    font-size: 12px;
    padding: 2px 6px;
    border-radius: 3px;
    transition: all 0.2s;
  }

  .clear-all-btn:hover {
    background: #fff5f5;
  }

  .preview-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
  }

  .preview-tag {
    display: inline-flex;
    align-items: center;
    background: white;
    border: 1px solid #d0d7de;
    border-radius: 3px;
    padding: 2px 6px;
    font-size: 11px;
    color: #24292f;
    max-width: 150px;
  }

  .preview-tag-text {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 120px;
  }

  .preview-tag-remove {
    background: none;
    border: none;
    color: #656d76;
    cursor: pointer;
    margin-left: 4px;
    font-size: 15px;
    line-height: 1;
    padding: 0;
  }

  .preview-tag-remove:hover {
    color: #da3633;
  }
</style>
    